#include "arch_espacios_libres.h"

ArchEspaciosLibres::ArchEspaciosLibres(std::string& nombre, unsigned int tam_bloque):ArchControl(nombre, tam_bloque){
}

int ArchEspaciosLibres::consultar_espacio_libre(unsigned int size_minimo) throw(ExcepArchCerrado){

	unsigned int cont_bloques = 0;
	bool encontrado = false;
	Bloque * bloque;
	int resultado = -1;
	unsigned int esp_libre_act;
	
	if (this-> fd != -1){
				
			while((cont_bloques <= (this->cant_bloques - 1)) && (!encontrado)){
				try{
					bloque = Buffer::get_instance()->get_bloque(*this,cont_bloques);
					unsigned int pos_reg = 0;
					if (cont_bloques == 0) pos_reg += TAM_REG;
					while((!encontrado) && (pos_reg < bloque->get_tope())){
						bloque->leer((char*) &esp_libre_act, pos_reg, TAM_REG);
						if (esp_libre_act >= size_minimo){
							encontrado = true;
							resultado = nbloque_to_slot(cont_bloques, pos_reg);
						}
						pos_reg += TAM_REG;
					}
					cont_bloques++;
					delete bloque;
					bloque = NULL;
				}
				catch (ExcepLeerBloque &e){
					if (bloque != NULL) delete (bloque);
					throw e;
				}
			}
		}else
			throw ExcepArchCerrado("Error - El archivo : "+this-> get_nombre() +" esta cerrado. ");
	
	return resultado;
}

unsigned int ArchEspaciosLibres::consultar_espacio_bloque(unsigned int num_bloque){
	return this->get_valor(num_bloque);
}

void ArchEspaciosLibres::actualizar_espacio_libre(unsigned int num_bloque,int valor_a_agregar){
	unsigned int esp_libre = 0;
	unsigned int nbloque = slot_to_nbloque(num_bloque);
	unsigned int offset = slot_to_despl(num_bloque);
	Bloque * bloque = Buffer::get_instance()->get_bloque(*this,nbloque);
	bloque->leer((char*) &esp_libre, offset, TAM_REG);
	esp_libre += valor_a_agregar;
	bloque->escribir((char*) &esp_libre, offset, TAM_REG);

	Buffer::get_instance()->guardar_bloque(*this, bloque);
	delete (bloque);
}

void ArchEspaciosLibres::set_espacio_libre(unsigned int num_bloque, unsigned int valor){
	this->set_valor(num_bloque, valor);
}

TiposArchivo ArchEspaciosLibres::get_tipo_archivo(){
	return ESPACIO_LIBRE;
}

unsigned int ArchEspaciosLibres::get_espacio_libre_datos() throw(ExcepArchCerrado, ExcepLeerBloque){
	
	unsigned int espacio_libre_total = 0;
	Bloque * bloque;
	unsigned int valor;
	
	for(unsigned int num_bloque = 0; num_bloque < this->cant_bloques; num_bloque++){
		unsigned int pos = 0;
		bloque = Buffer::get_instance()->get_bloque(*this,num_bloque);
		if (num_bloque == 0) pos+= TAM_REG;
		while (pos < bloque->get_tope()) {
			bloque->leer((char*) &valor, pos, TAM_REG);
			espacio_libre_total += valor;
			pos += TAM_REG;
		}
		delete bloque;
	}	
	return espacio_libre_total;
}
